package api

import (
	"api-gateway/basic/consts"
	"api-gateway/basic/global"
	"api-gateway/basic/model"
	"api-gateway/handler/pkg"
	"api-gateway/handler/request"
	"context"
	"encoding/json"
	"github.com/gin-gonic/gin"
	"github.com/google/uuid"
	"log"
	"net/http"
	"path/filepath"
	"strconv"
	"time"
)

func Login(c *gin.Context) {
	var req request.LoginReq
	if err := c.ShouldBind(&req); err != nil {
		c.JSON(http.StatusOK, gin.H{
			"msg":  "验证失败",
			"code": 500,
			"data": err.Error(),
		})
		return
	}
	var user model.User
	global.DB.Where("tel = ?", req.Tel).Find(&user)
	if user.Id == 0 {
		u := model.User{
			Tel:    req.Tel,
			Number: req.Num,
		}
		global.DB.Create(&u)
	}
	if user.Number != req.Num {
		c.JSON(http.StatusOK, gin.H{
			"msg":  "验证码错误",
			"code": 500,
			"data": nil,
		})
		return
	}
	token, _ := pkg.NewJWT(consts.JWT_KEY).CreateToken(pkg.CustomClaims{
		ID: uint(user.Id),
	})
	c.JSON(http.StatusOK, gin.H{
		"msg":  "OK",
		"code": 200,
		"data": token,
	})
}

func List(c *gin.Context) {
	var req request.ListReq
	if err := c.ShouldBind(&req); err != nil {
		c.JSON(http.StatusOK, gin.H{
			"msg":  "验证失败",
			"code": 500,
			"data": err.Error(),
		})
		return
	}
	page := req.Page
	if page <= 0 {
		page = 1
	}
	pageSize := req.Size
	switch {
	case pageSize > 100:
		pageSize = 100
	case pageSize <= 0:
		pageSize = 10
	}
	offset := (page - 1) * pageSize
	var h []model.Hospital
	query := global.DB.Model(&h)
	if req.Page != 0 && req.Size != 0 {
		query = query.Offset(int(offset)).Limit(int(pageSize)).Find(&h)
	} else {
		query = query.Find(&h)
	}
	c.JSON(http.StatusOK, gin.H{
		"msg":  "OK",
		"code": 200,
		"data": h,
	})
}

func TeamList(c *gin.Context) {
	var req request.TeamListReq
	if err := c.ShouldBind(&req); err != nil {
		c.JSON(http.StatusOK, gin.H{
			"msg":  "验证失败",
			"code": 500,
			"data": err.Error(),
		})
		return
	}
	var t []model.Team
	global.DB.Find(&t)
	c.JSON(http.StatusOK, gin.H{
		"msg":  "OK",
		"code": 200,
		"data": t,
	})
}

func DoctorList(c *gin.Context) {
	var req request.DoctorListReq
	if err := c.ShouldBind(&req); err != nil {
		c.JSON(http.StatusOK, gin.H{
			"msg":  "验证失败",
			"code": 500,
			"data": err.Error(),
		})
		return
	}
	var d []model.Doctor
	key := "order" + req.Order
	bytes, err := global.RDB.Get(context.Background(), key).Bytes()
	if err == nil {
		err = json.Unmarshal(bytes, &d)
		if err != nil {
			log.Println("继续从mysql中查询")
		} else {
			if req.Order == "desc" {
				global.DB.Order("doctor_number desc").Find(&d)
			} else {
				global.DB.Find(&d)
			}
			if req.Status != 0 {
				global.DB.Where("doctor_status = ?", req.Status).Find(&d)
			} else {
				global.DB.Find(&d)
			}
			if req.Ment != 0 {
				global.DB.Where("doctorment = ?", req.Ment).Find(&d)
			} else {
				global.DB.Find(&d)
			}
			c.JSON(http.StatusOK, gin.H{
				"msg":  "OK",
				"code": 200,
				"data": d,
			})
		}
	}
	if req.Order == "desc" {
		global.DB.Order("doctor_number desc").Find(&d)
	} else {
		global.DB.Find(&d)
	}
	if req.Status != 0 {
		global.DB.Where("doctor_status = ?", req.Status).Find(&d)
	} else {
		global.DB.Find(&d)
	}
	if req.Ment != 0 {
		global.DB.Where("doctorment = ?", req.Ment).Find(&d)
	} else {
		global.DB.Find(&d)
	}
	marshal, err := json.Marshal(&d)
	if err == nil {
		global.RDB.Set(context.Background(), key, marshal, time.Minute*5)
	}
	c.JSON(http.StatusOK, gin.H{
		"msg":  "OK",
		"code": 200,
		"data": d,
	})
}

var script = `
    redis.call("GET",KEYS[1])==ARGV[1] then
    return redis.call("DEL",KEYS[1])
    else
    return 0
    end
`

func Ding(c *gin.Context) {
	var req request.DingReq
	if err := c.ShouldBind(&req); err != nil {
		c.JSON(http.StatusOK, gin.H{
			"msg":  "验证失败",
			"code": 500,
			"data": err.Error(),
		})
		return
	}
	order_sn := uuid.NewString()
	key := "order_sn_" + order_sn
	value := uuid.NewString()
	ctx := context.Background()
	result, err := global.RDB.SetNX(ctx, key, value, time.Minute*5).Result()
	if err != nil {
		log.Println("获取锁失败")
	}
	if !result {
		log.Println("当前操作正在处理，请稍后再试")
	}
	defer func() {
		i, err := global.RDB.Eval(ctx, script, []string{key}, value).Int64()
		if err != nil {
			log.Println("释放锁失败")
		}
		if i == 0 {
			log.Println("锁已释放或不存在")
		}
	}()
	var d model.Doctor
	global.DB.Find(&d)
	amount := uint64(req.Num) * d.DoctorPrice
	o := model.Order{
		UserId:   c.GetUint64("userId"),
		OrderSn:  order_sn,
		Amount:   amount,
		DoctorId: d.Id,
		Payment:  req.Payment,
		Status:   req.Status,
	}
	global.DB.Create(&o)
	pay := pkg.AliPay{
		Subject:     "预约金额",
		OutTradeNo:  order_sn,
		TotalAmount: strconv.FormatUint(amount, 10),
	}
	s := pay.Pay()
	c.JSON(http.StatusOK, gin.H{
		"msg":  "OK",
		"code": 200,
		"data": s,
	})
}

func Update(c *gin.Context) {
	var req request.UpdateReq
	if err := c.ShouldBind(&req); err != nil {
		c.JSON(http.StatusOK, gin.H{
			"msg":  "验证失败",
			"code": 500,
			"data": err.Error(),
		})
		return
	}
	var d model.Doctor
	global.DB.Where("id = ?", req.Id).Find(&d)
	if d.Id == 0 {
		c.JSON(http.StatusOK, gin.H{
			"msg":  "医生不存在",
			"code": 500,
			"data": nil,
		})
		return
	}
	do := model.Doctor{
		Id:           req.Id,
		DoctorStatus: req.DoctorStatus,
	}
	global.DB.Updates(&do)
	c.JSON(http.StatusOK, gin.H{
		"msg":  "OK",
		"code": 200,
		"data": "update is success",
	})
}

func Chat(c *gin.Context) {
	var req request.ChatReq
	if err := c.ShouldBind(&req); err != nil {
		c.JSON(http.StatusOK, gin.H{
			"msg":  "验证失败",
			"code": 500,
			"data": err.Error(),
		})
		return
	}
	file, _ := c.FormFile("file")
	log.Println(file.Filename)
	ext := filepath.Ext(file.Filename)
	s := time.Now().Format("20060102150405") + ext
	if file.Size > 5*1024*1024 {
		c.JSON(http.StatusOK, gin.H{
			"msg":  "图片过大",
			"code": 500,
			"data": nil,
		})
		return
	}
	if ext != ".jpg" && ext != ".png" {
		c.JSON(http.StatusOK, gin.H{
			"msg":  "格式错误",
			"code": 500,
			"data": nil,
		})
		return
	}
	dst := "./" + file.Filename
	// 上传文件至指定的完整文件路径
	c.SaveUploadedFile(file, dst)
	oss := pkg.Oss(dst, s)
	var user model.User
	global.DB.Find(&user)
	var d model.Doctor
	global.DB.Find(&d)
	cc := model.Chat{
		DoctorId:  d.Id,
		UserId:    user.Id,
		ImagesUrl: oss,
		Message:   req.Message,
	}
	ccs := model.Chats{
		UserId:    user.Id,
		DoctorId:  d.Id,
		ImagesUrl: oss,
		Mesage:    req.Message,
	}
	model.CreateAnimals(global.DB, &cc, &ccs)
	ctx := context.Background()
	key := "message" + req.Message
	global.RDB.Set(ctx, key, req.Message, time.Hour*24)
	c.JSON(http.StatusOK, gin.H{
		"msg":  "OK",
		"code": 200,
		"data": "chat is success",
	})
}
